﻿using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Sgr.BackGroundTasks;

namespace Sgr.Email.BackGroundTasks
{
    /// <summary>
    /// 邮件发送后台任务
    /// </summary>
    public class EmailSenderBackGroundTask : IBackGroundTask<EmailSenderData>
    {
        private readonly IBackGroundTaskManager _backGroundTaskManager;
        private readonly ISmtpService _smtpService;
        private readonly EmailOptions _options;
        private readonly ILogger<EmailSenderBackGroundTask> _logger;

        /// <summary>
        /// 初始化邮件发送后台任务
        /// </summary>
        public EmailSenderBackGroundTask(
            IBackGroundTaskManager backGroundTaskManager,
            ISmtpService smtpService,
            ILogger<EmailSenderBackGroundTask> logger,
            IOptions<EmailOptions> options)
        {
            _backGroundTaskManager = backGroundTaskManager ?? throw new ArgumentNullException(nameof(backGroundTaskManager));
            _smtpService = smtpService ?? throw new ArgumentNullException(nameof(smtpService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
        }

        /// <summary>
        /// 执行邮件发送任务
        /// </summary>
        public async Task ExecuteAsync(EmailSenderData data, CancellationToken cancellationToken = default)
        {
            Check.NotNull(data, nameof(data));

            _logger.LogInformation(
                "开始后台任务，发送邮件: Id={Id}, To={To}, RetryCount={RetryCount}/{MaxRetryCount}",
                data.Id,
                string.Join(",", data.To),
                data.RetryCount,
                data.MaxRetryCount ?? this._options.MaxRetryCount);

            try
            {
                // 构建邮件消息
                var message = BuildMailMessage(data);

                // 发送邮件
                var result = await _smtpService.SendAsync(
                    SmtpInfo.Create(_options),
                    message: message,
                    cancellationToken);

                if (result.Succeeded)
                {
                    _logger.LogInformation("后台任务执行成功: {EmailId}", data.Id);
                    return;
                }

                _logger.LogWarning(
                    "邮件发送失败: Id={Id}, To={To}, Errors={Errors}",
                    data.Id,
                    string.Join(",", data.To),
                    string.Join("; ", result.Errors ?? Array.Empty<string>()));

                await HandleFailureAsync(data, cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex,
                    "邮件发送异常: Id={Id}, To={To}",
                    data.Id,
                    string.Join(",", data.To));

                await HandleFailureAsync(data, cancellationToken);
            }
        }

        private async Task HandleFailureAsync(EmailSenderData data, CancellationToken cancellationToken = default)
        {
            int maxRetryCount = data.MaxRetryCount ?? this._options.MaxRetryCount;
            // 如果还可以重试，创建新的重试任务
            if (data.RetryCount < maxRetryCount)
            {
                var retryData = new EmailSenderData
                {
                    Id = data.Id,
                    To = data.To,
                    Cc = data.Cc,
                    Bcc = data.Bcc,
                    Subject = data.Subject,
                    Body = data.Body,
                    IsBodyHtml = data.IsBodyHtml,
                    RetryCount = data.RetryCount + 1,
                    MaxRetryCount = maxRetryCount
                };

                // 通过任务调度系统重新创建任务
                await _backGroundTaskManager.EnqueueAsync<EmailSenderBackGroundTask, EmailSenderData>(retryData,
                    delay: TimeSpan.FromSeconds(_options.RetryIntervalSeconds),
                    cancellationToken);

                _logger.LogInformation(
                    "已创建重试任务: Id={Id}, To={To}, NextRetryCount={RetryCount}",
                    data.Id,
                    string.Join(",", data.To),
                    retryData.RetryCount);
            }
        }

        /// <summary>
        /// 构建邮件消息
        /// </summary>
        private static MailMessage BuildMailMessage(EmailSenderData data)
        {
            var message = new MailMessage
            {
                To = string.Join(",", data.To),
                Cc = string.Join(",", data.Cc),
                Bcc = string.Join(",", data.Bcc),
                Subject = data.Subject,
                Body = data.Body,
                IsBodyHtml = data.IsBodyHtml
            };

            return message;
        }
    }
}